package sim.utils.GenVarAle;

import sim.utils.rndGen.Random;

/**
 * Genera Variables Aleatorias que responden a una determinada Distribución de
 * Probabilidad. Las distribuciones pueden ser:
 * <ul>
 * <li>Distribución Uniforme.</li>
 * <li>Distribución Normal.</li>
 * <li>Distribución Exponencial Negativa.</li>
 * </ul>
 * 
 * @author alejandro
 * 
 */
public class VariableAleatoria {

	public static final int DISTRIBUCION_UNIFORME = 1;
	public static final int DISTRIBUCION_NORMAL = 2;
	public static final int DISTRIBUCION_EXP_NEGATIVA = 3;

	private Random generador;
	private int distribucion;
	private VariableGenerator variableGenerator;

	/**
	 * Constructor al cual se le pasa por parámetro el generador de Números
	 * Aleatorios.
	 * 
	 * @param generador
	 *            Una instancia de la clase "Random" que usa para generar los
	 *            valores de las variables.
	 */
	public VariableAleatoria(Random generador) {
		super();
		this.generador = generador;
	}

	/**
	 * Constructor al cual se le pasa por parámetro el método usado para generar
	 * los valores de las variables.
	 * 
	 * @param metodo
	 *            El método a usar. Debe ser algún método de la clase "Random".
	 */
	public VariableAleatoria(int metodo) {
		this(new Random(metodo));
	}

	/**
	 * Constructor por defecto. Utiliza el método nativo de Java para generar
	 * los valores de las variables.
	 */
	public VariableAleatoria() {
		this(Random.METODO_JAVA_NATIVO);
	}

	/**
	 * Configura el generador para generar Variables Aleatorias que respondan a
	 * la Distribución Uniforme.
	 * 
	 * @param minimo
	 *            El límite inferior (a) del generador.
	 * @param maximo
	 *            El límite superior (b) del generador.
	 */
	public void setUniforme(int minimo, int maximo) {
		this.distribucion = VariableAleatoria.DISTRIBUCION_UNIFORME;
		this.variableGenerator = new VGUniforme(minimo, maximo);
	}

	/**
	 * Configura el generador para generar Variables Aleatorias que respondan a
	 * la Distribución Normal.
	 * 
	 * @param media
	 *            La Media (μ) de la distribución normal.
	 * @param desviacion
	 *            la Desviación Standard (σ) de la distribución normal.
	 */
	public void setNormal(double media, double desviacion) {
		this.distribucion = VariableAleatoria.DISTRIBUCION_NORMAL;
		this.variableGenerator = new VGNormal(media, desviacion);
	}

	/**
	 * Configura el generador para generar Variables Aleatorias que respondan a
	 * la Distribución Exponencial Negativa. Se debe pasar la media de la
	 * variable la cual debe ser un valor de la forma [cant. de eventos] /
	 * [intervalo de tiempo].<br>
	 * Ejemplos:
	 * <ul>
	 * <li>1 persona cada 5 minutos [1/5]</li>
	 * <li>3 vehículos por hora [3/1] (en horas) o [3/60] (en minutos)</li>
	 * <li>5 aviones cada 2 dias [5/2] (en dias), [5/48] (en horas) o [5/2880]
	 * (en minutos)</li>
	 * </ul>
	 * 
	 * @param media
	 *            La Media (λ) de la distribución exponencial negativa.
	 */
	public void setExpNeg(double media) {
		this.distribucion = VariableAleatoria.DISTRIBUCION_EXP_NEGATIVA;
		this.variableGenerator = new VGExpNeg(media);
	}

	/**
	 * Devuelve un valor Aleatorio que responde a la Distribución de
	 * Probabilidad configurada.
	 * 
	 * @return El Valor de la Variable Aleatoria.
	 */
	public double next() {
		return variableGenerator.next();
	}
	
	/**
	 * Método que devuelve el número random usado para generar el último valor
	 * de la variable aleatoria para las ditribuciones uniforme y exponencial
	 * negativa.
	 * 
	 * @return El último random usado o -1 si no se generó ninguno.
	 */
	public double getLastRandom(){
		return this.variableGenerator.getLastRandom();
	}

	public Random getGenerador() {
		return generador;
	}

	public int getDistribucion() {
		return distribucion;
	}

}
